#include "FingerManager.h"

#if defined(_DEBUG) && defined(WIN32)
#ifndef DBG_NEW
#define DBG_NEW new ( _NORMAL_BLOCK , __FILE__ , __LINE__ )
#define new DBG_NEW
#endif
#endif

namespace Tutorial6
{
	/**
	* Constructor
	*/
	FingerManager::FingerManager()
	{
	}

	/**
	* Destructor
	*/
	FingerManager::~FingerManager()
	{
	}

	
	/**
	* Handles Finger Down events
	* \param inData Touch Event data container
	*/
	void FingerManager::onFingerDown(const TouchListener::TouchData& inData)
	{
		// add the touch data into the list
		mFingers.push_back(FingerStorage(inData));
	}

	/**
	* Handles Finger Up events
	* \param inData Touch Event data container
	*/
	void FingerManager::onFingerUp(const TouchListener::TouchData& inData)
	{
		// remove the touch from the list if its present
		removeFinger(inData.mID);
	}

	/**
	* Handles Finger Update events
	* \param inData Touch Event data container
	*/
	void FingerManager::onFingerUpdate(const TouchListener::TouchData& inData)
	{	
		// Checkk if the finger is present in the list
		FingerStorage *temp = findFinger(inData.mID);
		if(temp!= NULL)
		{
			// if found update its touch information
			TouchListener::TouchData *tempfinger = &temp->mFinger;
			if(tempfinger != NULL)
			{				
				if((QVector2D(inData.mX,inData.mY) - QVector2D(tempfinger->mX,tempfinger->mY)).lengthSquared()>0.0001f)
				{
					tempfinger->mDX = inData.mDX;
					tempfinger->mDY = inData.mDY;
					tempfinger->mX = inData.mX;
					tempfinger->mY = inData.mY;				
				}				
			}
		}		
	}

	/**
	* Iteratively checks for the touchID in the list
	* \param inID Id of the touch that needs to be searched
	* \return FingerStorage* if successful, NULL on failure
	*/
	FingerStorage* FingerManager::findFinger(int inID)
	{
		std::list<FingerStorage>::iterator iter;
		for(iter=mFingers.begin();iter!=mFingers.end();++iter)
		{
			if(iter->mFinger.mID == inID)
			{
				return &(*iter);
			}
		}
		return NULL;
	}

	/**
	* Removes the touch from the list if found
	* \param inID Id of the touch that needs to be removed
	* \return void
	*/
	void FingerManager::removeFinger(int inID)
	{		
		std::list<FingerStorage>::iterator iter;
		for(iter=mFingers.begin();iter!=mFingers.end();++iter)
		{
			if(iter->mFinger.mID == inID)
			{
				mFingers.erase(iter);				
				return;
			}
		}
	}

	/**
	* Calculates the change in distance between the latest touch points
	* \return float Returns delta value of change
	*/
	float FingerManager::distanceChange()
	{
		float totalchange = 0;
		std::list<FingerStorage>::iterator iter;
		for(iter=mFingers.begin();iter!=mFingers.end();++iter)
		{
			std::list<FingerStorage>::iterator iter2;
			for(iter2=mFingers.begin();iter2!=mFingers.end();++iter2)
			{
				if(iter != iter2)
				{
					TouchListener::TouchData *finger1 = &iter->mFinger;
					TouchListener::TouchData *finger2 = &iter2->mFinger;

					QVector2D origdist;
					origdist.setX((finger1->mX - finger1->mDX) - (finger2->mX - finger2->mDX));
					origdist.setY((finger1->mY - finger1->mDY) - (finger2->mY - finger2->mDY));

					QVector2D currentdist;
					currentdist.setX(finger1->mX - finger2->mX);
					currentdist.setY(finger1->mY - finger2->mY);

					totalchange += (currentdist.length() - origdist.length());
				}
			}				
		}
		totalchange /= mFingers.size();

		for(iter=mFingers.begin();iter!=mFingers.end();++iter)
		{
			iter->mFinger.mDX = 0;
			iter->mFinger.mDY = 0;
		}	
		return totalchange;
	}

	/**
	* Calculates the angle of change between the latest touch points
	* \return float Returns delta value of change
	*/
	float FingerManager::angleChange()
	{
		if(mFingers.empty())
			return 0;

		TouchListener::TouchData *finger1 = &mFingers.front().mFinger;
		TouchListener::TouchData *finger2 = &mFingers.back().mFinger;

		QVector2D origdist;
		origdist.setX((finger1->mX - finger1->mDX) - (finger2->mX - finger2->mDX));
		origdist.setY((finger1->mY - finger1->mDY) - (finger2->mY - finger2->mDY));

		QVector2D currentdist;
		currentdist.setX(finger1->mX - finger2->mX);
		currentdist.setY(finger1->mY - finger2->mY);

		float outangle = Blobz::radToDeg(Blobz::PI-atan2(origdist.x(),origdist.y()));
		float test = Blobz::radToDeg(Blobz::PI-atan2(currentdist.x(),currentdist.y()));

		return test - outangle;
	}
}